package com.example.demo.controller;

import com.example.demo.config.IMCommand;
import com.example.demo.config.IMCommandParameters;
import com.example.demo.config.IMOperations;
import com.example.demo.config.RTCOperations;
import com.example.demo.service.IMCosService;
import com.example.demo.support.IMBaseResponse;
import com.example.demo.support.IMDownloadHistoricMessagesResponse;
import com.example.demo.support.IMMessage;
import com.example.demo.support.UserSig;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import lombok.Data;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.apache.commons.io.IOUtils;
import org.springframework.web.bind.annotation.*;

import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPInputStream;

@RestController
@RequiredArgsConstructor
public class CommandController {

    @NonNull
    private IMOperations operations;

    @NonNull
    private RTCOperations rtcOperations;

    @NonNull
    private IMCommandParameters commandParameters;

    @NonNull
    private IMCosService IMCosService;

    @PostMapping("/user")
    public IMBaseResponse createUser(@RequestBody UserInfo userInfo) {
        return this.operations.executeCommand(IMCommand.ADD_ACCOUNT, this.commandParameters.addAccount(userInfo.getUserId(), userInfo.getNickname(), userInfo.getAvatar()));
    }

    @DeleteMapping("/user/{userId}")
    public IMBaseResponse deleteUser(@PathVariable String userId) {
        return this.operations.executeCommand(IMCommand.DELETE_ACCOUNT, this.commandParameters.deleteAccount(Lists.newArrayList(userId)));
    }

    @GetMapping("/userState/{userId}")
    public IMBaseResponse userState(@PathVariable String userId) {
        return this.operations.executeCommand(IMCommand.QUERY_USER_STATE, this.commandParameters.queryUserState(Lists.newArrayList(userId)));
    }

    @GetMapping("/sendTextMessage/{from}/{to}/{text}")
    public IMBaseResponse sendTextMessage(@PathVariable String from, @PathVariable String to, @PathVariable String text) {
        return this.operations.executeCommand(IMCommand.SEND_MESSAGE, this.commandParameters.sendTextMessage(from, to, text));
    }

    @GetMapping("/sig/{userId}")
    public UserSig genSig(@PathVariable String userId) {
        return this.operations.genUserSig(userId);
    }

    @GetMapping("/rtcSig/{userId}")
    public UserSig genRtcSig(@PathVariable String userId) {
        return this.rtcOperations.genUserSig(userId);
    }

    @GetMapping("/userInfo/{userId}")
    public IMBaseResponse userInfo(@PathVariable String userId) {
        return this.operations.executeCommand(IMCommand.QUERY_USER_INFO, this.commandParameters.queryUserInfo(Lists.newArrayList(userId)));
    }

    @Data
    public static class UserInfo {
        private String userId;
        private String gender;
        private String nickname;
        private Integer birthday;
        private String location;
        private String avatar;
        private String desc;
    }

    @PostMapping("/userInfo")
    public IMBaseResponse setUserInfo(@RequestBody UserInfo userInfo) {
        return this.operations.executeCommand(IMCommand.SET_USER_INFO, this.commandParameters.setUserInfo(userInfo.getUserId(), userInfo.getNickname(), IMCommandParameters.Gender.valueOf(userInfo.getGender()), userInfo.getBirthday(), userInfo.getAvatar(), userInfo.getLocation(), userInfo.getDesc()));
    }

    @GetMapping("/history/{type}/{time}")
    public Object downloadHistoricMessages(@PathVariable String type, @PathVariable String time) throws Exception {
        IMDownloadHistoricMessagesResponse response = (IMDownloadHistoricMessagesResponse) this.operations.executeCommand(IMCommand.DOWNLOAD_HISTORIC_MESSAGES, this.commandParameters.downloadHistoricMessages(IMCommandParameters.ChatType.valueOf(type), time));
        if (response.isSuccess()) {
            IMDownloadHistoricMessagesResponse.FileInfo info = response.getFile().get(0);
            URL url = new URL(info.getURL());
            URLConnection connection = url.openConnection();
            GZIPInputStream gzipInputStream = new GZIPInputStream(connection.getInputStream());
            String messages = IOUtils.toString(gzipInputStream, StandardCharsets.UTF_8);
            List<IMMessage> messageList = this.operations.parseMessages(new Gson().fromJson(messages, TypeToken.getParameterized(Map.class, String.class, Object.class).getType()));
            response.setParsedMessages(messageList);
            System.out.println(messages);
        }
        return response;
    }

    @GetMapping("/buckets")
    public Object listBuckets() {
        return this.IMCosService.listBuckets();
    }

    @Data
    public static class UploadParams {
        private String url;
        private String fileType;
    }

    @PostMapping("/upload")
    public Object uploadFile(@RequestBody UploadParams uploadParams) throws Exception {
//        String url = "https://cos.ap-shanghai.myqcloud.com/7923-shanghai-007-shared-04-1256635546/fdf4-1400312264/6bbb-test4/test4-test3-19746-tmp_a57c244abd5722a1795c572ac8f7ca9ece934c7859420c6d.jpg";
        String url = uploadParams.getUrl();
        return this.IMCosService.upload(url, com.example.demo.service.IMCosService.FileType.valueOf(uploadParams.getFileType()));
    }

    @Data
    public static class GroupInfo {
        private String groupId;
        private String name;
        private String introduction;
        private String notification;
        private String avatar;
        private List<String> memberIds;
    }

    @PostMapping("/group")
    public IMBaseResponse group(@RequestBody GroupInfo groupInfo) {
        return this.operations.executeCommand(IMCommand.CREATE_GROUP, this.commandParameters.createGroup(groupInfo.getGroupId(), groupInfo.getName(), groupInfo.getIntroduction(), groupInfo.getNotification(), groupInfo.getAvatar(), groupInfo.memberIds));
    }

    @DeleteMapping("/group/{groupId}")
    public IMBaseResponse group(@PathVariable String groupId) {
        return this.operations.executeCommand(IMCommand.DESTROY_GROUP, this.commandParameters.destroyGroup(groupId));
    }
}
